<?php

/**
 * GDF会员购 SDK
 * @author chenyun
 */

namespace App\Service\VendorClient\Shopgdf;
use App\Service\Code\Normal;
use App\Service\TaskServer\TaskWorker;
use Service\AppService\IdService;
use Swoole\Coroutine\WaitGroup;

class ShopgdfApiClient
{
    private $account  = 'shopgdf';
    protected $config;
    protected $RouteMap = [
        'createOrder'          => '/api/order/create',
        'cancelOrder'          => '/api/refund/apply',
        'queryOrderExpress'    => '/api/logistics/detail',
        'queryGoodsList'       => '/api/goods/list',
        'queryGoodsDetail'     => '/api/goods/detail',
    ];
    /**
     * 初始参数
     * @param obj $collection
     */
    public function __construct( $apiBody = [] ) 
    {
        $this->config = $apiBody;
    }
    
    /**
     * 创建订单
     */
    public function createOrder( $params = [] ) 
    {   
        ini_set('serialize_precision', 16);
        if( empty($params['supplierOrder']) || empty($params['orderGoods']) || empty($params['order']) || empty($params['binfo']) ) {
            return Normal::returnCode(Normal::FAIL,"except param supplierOrder or orderGoods or order or binfo");
        }
        //组装订单参数
        $orderInfo = $params['supplierOrder'];
        $order     = $params['order'];
        $binfo     = $params['binfo'];
        //运费
        $deliver_money  = $orderInfo['deliver_money'];
        //商品下单组
        $goods = [];
        $totalGoodsMoney = $freight = $productAmt = 0 ;
        foreach ($params['orderGoods'] as $key => $item )
        {
            //barcode
            $cit_cnname     = $item['goods_name'];
            //barcode
            $barcode        = $item['barcode'];
            //cit_code
            $cit_code       = $item['supplier_skucode'];
            //卖价
            $price              = $item['price'];
            //商品购买规格数量
            $spec_num           = $item['spec_num'];
            //商品购买数量(下单数量 X 起售数量)
            $quantity           = $item['quantity'];
            //实际购买数量
            $buyAcount          = $spec_num * $quantity;
        
            $singlePrice        = bcdiv($price, $spec_num,3);
            $singlePrice        = bcmul($singlePrice, 100,1);
            $singlePrice        = bcdiv(ceil($singlePrice), 100,2);
            $totalGoodsMoney    = bcmul($singlePrice, $buyAcount,2);
        
            //开始进行组装商品
            $goods[]=[
                "barcode"       => $barcode,
                "cit_code"      => $cit_code,
                "cit_cnname"    => $cit_cnname,
                "price"         => $singlePrice,
                "active_cut"    => $singlePrice,
                "count"         => $buyAcount,
                "active_type"   => 0,
            ];
            $productAmt = bcadd((string)$productAmt,(string)$totalGoodsMoney,2);
        }
        //优惠金额
        $discountMoney      = $orderInfo['discountMoney'] ?? 0.00;
        //总运费(运费 +运费税)
        $delivery       = bcadd((string)$freight, 0.00,2);
        //下单总金额(商品总金额 + 总运费)
        $totalMoney     = bcadd((string)$totalGoodsMoney,(string)$delivery,2);
        
        $payTime        = empty($order['payTime']) ? $orderInfo['pay_time'] :$order['payTime'];
        //支付时间
        $pay_time       = $payTime ? $payTime : time();
        $pay_time       = date('Y-m-d H:i:s',$payTime);
        
        //支付流水号
        $pay_sn         = $order['paySerial'] ?? $orderInfo['pay_sn'];
        
        $timestamp=time();
        $data = [
            'mer_code'    => $this->config["mer_code"],
            'data'        => [
                'mer_order_sn'              => $orderInfo['supplier_dsn'],
                'price'                     => $totalGoodsMoney,
                'express_money'             => "0",
                'coupon_money'              => "0",
                'bonus_money'               => "0",
                'discount_money'            => "0",
                'integral_money'            => "0",
                'real_pay_money'            => $totalGoodsMoney,
                'trade_pay_status'         => 1,
                'pay_time'                  => $payTime,
                'trade_number'              => $pay_sn,
                'create_time'               => time(),
                'receiver_name'             => $orderInfo['buyer_realname'],
                'receiver_mobile'           => $orderInfo['buyer_phone'],
                'receiver_province_name'    => $orderInfo['province'],
                'receiver_city_name'        => $orderInfo['city'],
                'receiver_district_name'    => $orderInfo['district'],
                'receiver_street_name'      => $orderInfo['receive_address'],
                'receiver_address_detail'   => $orderInfo['receive_address'],
                'third_kill_money'          => "0",
                'goods'                     => $goods,
            ],
            'timestamp'   => $timestamp,
            'sign'        => $this->getSign($timestamp),
        ];
        $requestParam = [
            'method'    => 'createOrder',
            'data'      => $data,
        ];
        return $this->createOrderExecute($requestParam);
    }
    

    /**
     * 订单支付
     * @param array $params
     * @return mixed
     */
    public function orderPay( $params = [] )
    {
        $orderSupplier      = $params['supplierOrder'];
        $order              = $params['order'];
        
        $mer_order_sn       = $orderSupplier['supplier_dsn'];
        
        //支付拓展信息
        $apply_extends      = @json_decode($orderSupplier['apply_extends'],true);
        $apply_extends      = empty($apply_extends) ? $order : $apply_extends;
        $payTime="";
        //支付时间
        if(isset($apply_extends['payTime']) && empty($apply_extends['payTime'])){
            $payTime = $apply_extends['pay_time'];
        }
        if(isset($order['payTime']) && empty($order['payTime'])){
            $payTime = $order['pay_time'];
        }
        $pay_time       = $payTime ? $payTime : time();
        $timestamp=time();
        $data = [
            'mer_code'    => $this->config["mer_code"],
            'data'        => [
                'mer_order_sn'  => $mer_order_sn,
                'trade_number'  => $apply_extends["paySerial"],
                'pay_time'      => $pay_time,
            ],
            'timestamp'   => $timestamp,
            'sign'        => $this->getSign($timestamp),
        ];
        $requestParam = [
            'method'    => 'orderPay',
            'data'      => $data,
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 获取取消订单
     */
    public function cancelOrder( $params = [] )
    {
        $orderSupplier      = $params['supplierOrder'];
        $order              = $params['order'];
        $orderGoods         = $params['orderGoods'];
        $costprice          = array_sum(array_column($orderGoods,'costprice'));
        $timestamp=time();
        if(empty($orderSupplier["thirdpart_order_sn"])){
            return Normal::returnCode(Normal::FAIL,"供应商订单号还没有回传，暂不支持退款");
        }
        $data = [
            'data'=> [
                'mer_orderid'       => $orderSupplier["supplier_dsn"],
                'order_sn'          => $orderSupplier["thirdpart_order_sn"],
                'refund_desc'       => $order['exceptReason'] ?? '申请订单退款作废,不要了',
                'refund_money'      => (string)$costprice,
                'refund_reason'     => $order['exceptReason'] ?? '申请订单退款作废,不要了',
                'user_mobile'       => $orderSupplier["buyer_phone"],
                'user_name'         => $orderSupplier["buyer_realname"],
                'refund_type'       => 1,
                'refund_express'    => "",
            ],
            'mer_code'    => $this->config["mer_code"],
            'timestamp'   => $timestamp,
            'sign'        => $this->getSign($timestamp),
        ];
        $requestParam = [
            'method'    => 'cancelOrder',
            'data'      => $data
        ];
        $res = $this->execute($requestParam);
        if($res["code"] != Normal::SUC && $res["msg"] =="已经申请过退款，待审核状态，请勿重复申请"){
            return Normal::returnCode(Normal::SUC,"操作成功");
        }
        return $res;
    }
   
    /**
     * 查询商品信息
     */
    public function queryGoodsList( $params = [] )
    {
       $barcode = [];
       if(isset($this->config["barcode"])){
           $barcode = explode(",",$this->config["barcode"]);
       }
           
       $timestamp=time();
       $data = [
            'mer_code'   => $this->config["mer_code"],
            'timestamp'  => $timestamp,
            'sign'       => $this->getSign($timestamp),
            'data'       =>[
                'page'      => $params['page'] ?? 1,
                'status'    => 1,
                'barcode'   => $barcode,
            ]
        ];
        $requestParam = [
            'method'    => 'queryGoodsList',
            'data'      => $data,
        ];
        $res = $this->execute($requestParam);
        if( $res['code'] == Normal::SUC ) {
            //批量获取商品详情
            $resDetails = $this->queryGoodsDetails(array_column($res['data']['list'],'barcode'));
            $newData = [];
            foreach($res['data']['list'] as $value){
                $value['description'] = "";
                if(isset($resDetails[$value['barcode']])){
                    $value['description'] = $resDetails[$value['barcode']]['description'];
                }
                if(isset($this->config["price_fields"])){
                    //如果设置了活动价，就将活动价覆盖供货价
                    if($this->config["price_fields"] == "promotionPrice"){
                        if(!empty($value["activityInfo"])){
                            $value["supply_price"] = $value["activityInfo"]["promotionPrice"]??0.00;
                        }
                    }
                }
                $newData[] = $value;
            } 
            $res['data']['list'] = $newData;
        }
        return $res;
    }

    public function queryGoodsDetails($barCodes){
        $details = [];
        $count = count($barCodes);
        $wg = new WaitGroup();
        $wg->add($count);
        foreach ($barCodes as $barCode){
            co(function () use ($wg,$barCode,& $details) {
                $requestParam = [
                    'barcode'   => $barCode,
                ];
                $responseParam = $this->queryGoodsDetail($requestParam);
                if ($responseParam['code'] == Normal::SUC && !empty($responseParam['data'])){
                      $details[$responseParam['data']['barcode']] = $responseParam['data'];
                }
                $wg->done();
            });
        }
        $wg->wait();
        return $details;
    }

     /**
     * 查询商品信息
     */
    public function queryGoodsDetail( $params = [] )
    {
       $timestamp=time();
       $data = [
            'mer_code'   => $this->config["mer_code"],
            'timestamp'  => $timestamp,
            'sign'       => $this->getSign($timestamp),
            'data'       =>[
                'barcode'  => $params['barcode'],
            ]
        ];
        $requestParam = [
            'method'    => 'queryGoodsDetail',
            'data'      => $data,
        ];
        $res = $this->execute($requestParam);
        
        return $res;
    }
    
    /**
     * 加签
     * @param array $param
     */
    protected function getSign($timestamp)
    {
        //MD5(mer_code=【商户编码】&timestamp=【当前时间戳】&【秘钥】),然后转大写;
        //sign = MD5(mer_code=100010&timestamp=1642140596&E9976AD56094E84C97871B1FD8EBC2E2);
        //sign = (转大写)44BBEC9B64CB55FCA13280E051890C59
        $mer_code=$this->config["mer_code"];
        $mer_secret=$this->config["mer_secret"];
        $Sign=md5("mer_code=".$mer_code."&"."timestamp=".$timestamp."&".$mer_secret);
        return strtoupper($Sign);
    }
    /**
     * CURL请求-0
     * @param $params
     * @return mixed
     */
    public function execute( $param = [] )  
    {
        if(empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        }
        $method = $param['method'];
        $url = $this->config['baseurl'].$this->RouteMap[$method];
        $parameter = [
             [
                'tag'       => $this->account.'_'.$method,
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $url,
                'data'      => $param['data'],
                'method'    => 'post',
                'format'    => 'json',
                'header'    => [
                    "Content-Type:application/json",
                ],
        
            ],
        ];
        if( in_array($method,['queryGoodsList','queryGoodsDetail']) ) {
            $resTask = TaskWorker::instance()->addTask($parameter,'handleDiableTask');
        } else {
            $resTask = TaskWorker::instance()->addTask($parameter);
        }
        $resTask = current($resTask);
        $res     = $resTask['response']['result']; 
        $resHttp = @json_decode($res, true);
        
        if( isset($resHttp['code']) && $resHttp['code']==200 ) {
            return Normal::returnCode(Normal::SUC,"操作成功",$resHttp["data"]);
        }
        $message = isset($resHttp['message']) ? $resHttp['message'] : '请求失败';
        return Normal::returnCode(Normal::FAIL,$message);
    }
    
    /**
     * CURL请求-0
     * @param $params
     * @return mixed
     */
    public function createOrderExecute( $param = [] )
    {
        if(empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        }
        $method = $param['method'];
        $url = $this->config['baseurl'].$this->RouteMap[$method];
        $parameter = [
            [
                'tag'       => $this->account.'_'.$method,
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $url,
                'data'      => $param['data'],
                'method'    => 'post',
                'format'    => 'json',
                'header'    => [
                    "Content-Type:application/json",
                ],
    
            ],
        ];
        $resTask = TaskWorker::instance()->addTask($parameter);
        $resTask = current($resTask);
        $res     = $resTask['response']['result'];
        $resHttp = @json_decode($res, true);
        if( isset($resHttp['code']) && $resHttp['code']==200 ) {
            return Normal::returnCode(Normal::SUC,"操作成功",$parameter);
        }
        $message = isset($resHttp['message']) ? $resHttp['message'] : '请求失败';
        return Normal::returnCode(Normal::FAIL,$message);
    }
}